library(httr2)library(sf)library(dplyr)library(purrr)library(jsonlite)download_tree_points <-function(limit =50000) {# Create folder if neededdir.create("data/mp03", showWarnings =FALSE, recursive =TRUE)# Correct NYC Tree Census API - use JSON not GeoJSON base_url <-"https://data.cityofnewyork.us/resource/nwxe-4ae8.json" offset <-0 all_data <-list()repeat {message(paste("Downloading records", offset, "to", offset + limit, "...")) req <-request(base_url) |>req_url_query(`$limit`= limit, `$offset`= offset) resp <-req_perform(req) data_chunk <-resp_body_json(resp, simplifyVector =TRUE)# Stop if no more dataif (nrow(data_chunk) ==0) break all_data[[length(all_data) +1]] <- data_chunk# Stop if fewer than limit rowsif (nrow(data_chunk) < limit) break offset <- offset + limit }# Combine all chunksmessage("Combining all downloaded data...") tree_data <-bind_rows(all_data)message(paste("Total trees loaded:", nrow(tree_data)))return(tree_data)}# Download the datatrees_raw <-download_tree_points(limit =50000)# Convert to sf object with proper geometrytrees_sf <- trees_raw %>%filter(!is.na(latitude) &!is.na(longitude)) %>%st_as_sf(coords =c("longitude", "latitude"), crs =4326) %>%st_transform(crs ="WGS84")# Verify it workedcat("Trees downloaded:", nrow(trees_sf), "\n")cat("Geometry type:", paste(unique(st_geometry_type(trees_sf)), collapse=", "), "\n")glimpse(trees_sf)
DATA INTEGRATION AND INTIAL EXPLORATION
MAPPING NYC TREES
TASK 3: PLOT ALL TREE POINTS
Show Code
## TASK 3: PLOT ALL TREE POINTS #| message: false#| warning: falselibrary(ggplot2)library(dplyr)library(sf)plot_trees <-function(tree_data, council_data, n_trees =10000) {# Ensure both are in same CRS council_simplified <- council_data %>%st_transform(crs ="WGS84") %>%mutate(geometry =st_simplify(geometry, dTolerance =5)) tree_data <-st_transform(tree_data, crs ="WGS84")# Sample treesif (n_trees <nrow(tree_data)) {set.seed(123) trees_sample <- tree_data %>%slice_sample(n = n_trees) } else { trees_sample <- tree_data }ggplot() +geom_sf(data = council_simplified, fill ="white", color ="gray20", linewidth =0.3) +geom_sf(data = trees_sample,color ="forestgreen", alpha =0.3, size =0.8) +labs(title =paste("NYC Tree Map (", format(n_trees, big.mark=","), " Trees)", sep=""),subtitle ="Overlay on City Council Districts",caption ="Data: NYC OpenData & NYC Planning" ) +theme_minimal() +theme(plot.title =element_text(face ="bold", size =16),plot.subtitle =element_text(size =12),panel.background =element_rect(fill ="white"),panel.grid =element_line(color ="gray95") )}
Show Code
# Plot trees - try with more for better visibilityplot_trees(trees_sf, council, n_trees =5000)
## EXTRA CREDIT - 1 Interactive Visualization
Show Code
library(plotly)library(leaflet)library(htmlwidgets)# Create interactive map using leaflet# Leaflet is better for geospatial interactive maps than plotly# Sample trees for performance (10,000 points)set.seed(123)trees_sample <- trees_sf %>%slice_sample(n =10000) %>%mutate(species_info =paste0("<b>", spc_common, "</b><br>","Address: ", address, "<br>","Status: ", status) )# Extract coordinates for leaflettree_coords <-st_coordinates(trees_sample)trees_sample$lon <- tree_coords[, "X"]trees_sample$lat <- tree_coords[, "Y"]# Create leaflet mapinteractive_map <-leaflet(width ="100%", height ="600px") %>%addProviderTiles(providers$CartoDB.Positron) %>%# Add council district boundariesaddPolygons(data = council %>%st_transform(crs =4326),fillColor ="transparent",color ="black",weight =2,opacity =0.7,label =~paste("Council District", CounDist),group ="Districts" ) %>%# Add tree pointsaddCircleMarkers(data = trees_sample,lng =~lon,lat =~lat,radius =3,color ="darkgreen",fillColor ="forestgreen",fillOpacity =0.6,stroke =FALSE,popup =~species_info,label =~spc_common,group ="Trees",clusterOptions =markerClusterOptions() ) %>%# Add layer controlsaddLayersControl(overlayGroups =c("Districts", "Trees"),options =layersControlOptions(collapsed =FALSE) ) %>%# Add scale bar and reset view buttonaddScaleBar(position ="bottomleft") %>%# Set initial view to NYCsetView(lng =-73.935242, lat =40.730610, zoom =11)interactive_map
Interactive Features: - Zoom and Pan: Use mouse wheel or pinch to zoom, click and drag to pan - Click Trees: Click individual tree markers to see species, address, status, and district - Hover: Hover over trees to see species name - Clustering: Trees are clustered at higher zoom levels for better performance - zoom in to see individual trees - Layer Control: Toggle district boundaries and tree layers on/off using the control in the top right - Reset View: Double-click to reset view
TASK 4: DISTRICT-LEVEL ANALYSIS OF TREE COVERAGE
Show Code
library(sf)library(dplyr)library(ggplot2)# Perform spatial join: which district contains each tree?trees_with_districts <-st_join(trees_sf, council, join = st_intersects)# View the joined data structurecat("Total trees with district info:", nrow(trees_with_districts), "\n")
Total trees with district info: 683788
Question 1: Which council district has the most trees?
Show Code
library(knitr)district_tree_counts <- trees_with_districts %>%st_drop_geometry() %>%filter(!is.na(CounDist)) %>%count(CounDist, name ="tree_count") %>%arrange(desc(tree_count))# Create formatted table for top 10 with row numbersdistrict_tree_counts %>%head(10) %>%mutate(Rank =row_number()) %>%select(Rank, CounDist, tree_count) %>%kable(col.names =c("", "Council District", "Number of Trees"),format.args =list(big.mark =","),caption ="Table 1: Top 10 NYC Council Districts by Tree Count",align =c("c", "c", "c") # 3 columns: Rank, CounDist, tree_count )
Table 1: Top 10 NYC Council Districts by Tree Count
Council District
Number of Trees
1
51
52,728
2
19
34,756
3
50
33,256
4
23
31,570
5
31
22,519
6
49
20,621
7
32
19,736
8
27
18,958
9
24
18,809
10
13
17,532
Show Code
# Answer in textmost_trees_district <- district_tree_counts %>%slice(1)cat("\nDistrict", most_trees_district$CounDist, "has the most trees, with", format(most_trees_district$tree_count, big.mark=","), "trees.\n")
District 51 has the most trees, with 52,728 trees.
Question 2: Which council district has the highest density of trees?
Show Code
library(knitr)district_density <- trees_with_districts %>%st_drop_geometry() %>%filter(!is.na(CounDist)) %>%count(CounDist, name ="tree_count") %>%left_join(council %>%st_drop_geometry() %>%select(CounDist, Shape_Area), by ="CounDist") %>%mutate(tree_density = tree_count / Shape_Area) %>%arrange(desc(tree_density))# Formatted tabledistrict_density %>%head(10) %>%mutate(Rank =row_number()) %>%select(Rank, CounDist, tree_count, tree_density) %>%kable(col.names =c("", "Council District", "Number of Trees", "Tree Density"),format.args =list(big.mark =","),caption ="Table 2: Top 10 NYC Council Districts by Tree Density",align =c("c", "c", "c", "c"),digits =c(0, 0, 0, 6) )
Table 2: Top 10 NYC Council Districts by Tree Density
Council District
Number of Trees
Tree Density
1
9
8,175
0.000145
2
5
5,249
0.000139
3
7
7,338
0.000133
4
44
12,854
0.000130
5
35
10,202
0.000128
6
25
7,977
0.000125
7
14
6,476
0.000123
8
2
5,920
0.000123
9
39
14,454
0.000122
10
4
8,031
0.000120
Show Code
# Answerhighest_density <- district_density %>%slice(1)cat("\nCouncil District", highest_density$CounDist, "has the highest tree density with", format(highest_density$tree_density, scientific =FALSE, digits =6), "trees per square unit.\n")
Council District 9 has the highest tree density with 0.000145298 trees per square unit.
Question 3: Which district has highest fraction of dead trees?
Show Code
library(knitr)# Check unique values in tree condition columncat("Tree status values:\n")
Table 3: Top 10 NYC Council Districts by Dead Tree Percentage
Council District
Total Trees
Dead Trees
Dead Tree %
1
16
6,897
395
5.73
2
15
8,494
369
4.34
3
8
6,944
278
4.00
4
17
11,137
444
3.99
5
10
7,009
266
3.80
6
3
7,521
278
3.70
7
14
6,476
238
3.68
8
34
10,578
346
3.27
9
1
5,555
172
3.10
10
9
8,175
235
2.87
Show Code
# Answerhighest_dead <- dead_tree_fraction %>%slice(1)cat("\nCouncil District", highest_dead$CounDist, "has the highest fraction of dead trees at", round(highest_dead$dead_fraction *100, 2), "%.\n")
Council District 16 has the highest fraction of dead trees at 5.73 %.
Question 4: What is the most common tree species in Manhattan?
Show Code
library(knitr)# Add borough information based on district rangestrees_with_borough <- trees_with_districts %>%mutate(Borough =case_when( CounDist >=1& CounDist <=10~"Manhattan", CounDist >=11& CounDist <=18~"Bronx", CounDist >=19& CounDist <=32~"Queens", CounDist >=33& CounDist <=48~"Brooklyn", CounDist >=49& CounDist <=51~"Staten Island",TRUE~NA_character_ ))manhattan_species <- trees_with_borough %>%st_drop_geometry() %>%filter(Borough =="Manhattan", !is.na(spc_common)) %>%count(spc_common, sort =TRUE)# Formatted tablemanhattan_species %>%head(10) %>%mutate(Rank =row_number()) %>%select(Rank, spc_common, n) %>%kable(col.names =c("", "Tree Species", "Count"),format.args =list(big.mark =","),caption ="Table 4: Top 10 Most Common Tree Species in Manhattan",align =c("c", "l", "c") )
Table 4: Top 10 Most Common Tree Species in Manhattan
Tree Species
Count
1
honeylocust
13,644
2
Callery pear
7,498
3
ginkgo
5,961
4
pin oak
4,813
5
Sophora
4,608
6
London planetree
4,420
7
Japanese zelkova
3,861
8
littleleaf linden
3,527
9
American elm
1,793
10
American linden
1,760
Show Code
# Answermost_common_manhattan <- manhattan_species %>%slice(1)cat("\nThe most common tree species in Manhattan is", most_common_manhattan$spc_common, "with", format(most_common_manhattan$n, big.mark=","), "trees.\n")
The most common tree species in Manhattan is honeylocust with 13,644 trees.
Question 5: What is the species of the tree closest to Baruch’s campus?
Show Code
# Create helper function for point creationnew_st_point <-function(lon, lat) {st_sfc(st_point(c(lon, lat))) %>%st_set_crs("WGS84")}# Baruch College coordinates (Lexington Ave & E 24th St)baruch_point <-new_st_point(-73.9838, 40.7402)# Calculate distance from each tree to Baruchtrees_with_distance <- trees_sf %>%mutate(distance =st_distance(geometry, baruch_point))# Find closest treeclosest_tree <- trees_with_distance %>%arrange(distance) %>%slice(1)closest_info <-st_drop_geometry(closest_tree) %>%select(spc_common, address, distance)print(closest_info)
spc_common address distance
1 sawtooth oak 148 EAST 24 STREET 30.39175 [m]
Show Code
cat("\nThe tree closest to Baruch's campus is a", closest_tree$spc_common, "located at", closest_tree$address, "\nDistance:", round(as.numeric(closest_tree$distance), 2), "meters.\n")
The tree closest to Baruch's campus is a sawtooth oak located at 148 EAST 24 STREET
Distance: 30.39 meters.
EXTRA CREDIT - 2: Additional Parks Department Data
These additional datasets provide context on safety risks and ongoing maintenance work orders across NYC’s urban forest, supporting our proposal for targeted intervention in District 19.
TASK 5: NYC PARKS PROPOSAL
Growing a greener NYC, one tree at a time
Government Project Design: Dead Tree Replacement Program for Council District 19
Introduction
Council District 19, located in northeastern Queens, faces a critical urban forestry challenge that demands immediate attention. With a diverse mix of residential neighborhoods including Flushing, Whitestone, and College Point, this district serves as home to thousands of families who deserve healthy, thriving street trees that provide shade, improve air quality, and enhance property values.
Project Description
I propose the “Queens Green Revival Initiative” - a comprehensive dead tree replacement and urban canopy enhancement program for Council District 19. This program will systematically identify, remove, and replace all dead and dying trees with climate-resilient native species. Additionally, we will address vacant tree pits and stumps with new plantings, prioritizing species that provide maximum environmental benefits while being resistant to urban stressors and climate change impacts.
Based on the latest NYC Street Tree Census data, Council District 19 currently contains 34,756 street trees. Our comprehensive assessment reveals:
441 dead trees requiring immediate removal and replacement
0 trees in poor condition needing intervention or replacement
997 existing stumps to be removed and replanted
Total intervention sites: 1438 tree locations
This initiative will directly impact approximately 4.1% of the district’s urban forest, representing a significant investment in our community’s environmental future.
Zoomed-In District Visualization
Show Code
# Create visualization focused on district 19ggplot() +geom_sf(data = district_boundary, fill ="lightgray", color ="black", linewidth =1.2) +geom_sf(data = district_trees %>%filter(status =="Alive"), color ="darkgreen", alpha =0.3, size =0.5) +geom_sf(data = district_trees %>%filter(status %in%c("Dead", "Stump", "Poor")), color ="red", size =1.2, alpha =0.7) +labs(title =paste("Tree Health Status in Council District", target_district),subtitle ="Red points indicate dead trees, stumps, and trees in poor condition requiring intervention",caption ="Data: NYC Parks Department Street Tree Census" ) +theme_minimal() +theme(plot.title =element_text(face ="bold", size =16),plot.subtitle =element_text(size =11),axis.text =element_text(size =9) )
This map clearly shows the spatial distribution of problematic trees (in red) throughout District 19, demonstrating the widespread nature of the challenge and the need for a comprehensive, district-wide intervention.
Comparative Analysis: Why District 19?
To demonstrate why Council District 19 is a priority for this investment, I have compared it with three neighboring Queens districts (Districts 20, 23, and 24) on key metrics:
Table 5: Comparison of Tree Health Across Queens Districts
Council District
Total Trees
Problematic Trees
Problem %
1
20
14,431
750
5.20
2
23
31,570
1,556
4.93
3
19
34,756
1,438
4.14
4
24
18,809
764
4.06
As this comparison demonstrates, Council District 19 has 4.14% of its trees in problematic condition, making it a high-priority district for intervention among comparable Queens communities.
Visual Comparison: Problem Tree Distribution
Show Code
# Bar chart comparing districtsggplot(district_comparison, aes(x =factor(CounDist), y = problem_percentage, fill =factor(CounDist))) +geom_col(show.legend =FALSE, width =0.7) +geom_text(aes(label =paste0(problem_percentage, "%")), vjust =-0.5, size =5, fontface ="bold") +scale_fill_manual(values =c("19"="#d32f2f", "20"="#7cb342", "23"="#7cb342", "24"="#7cb342")) +labs(title ="Percentage of Problematic Trees by Council District",subtitle ="District 19 (highlighted in red) shows the highest percentage of trees requiring intervention",x ="Council District",y ="Problematic Trees (%)",caption ="Problematic trees = Dead + Poor Condition + Stumps" ) +theme_minimal() +theme(plot.title =element_text(face ="bold", size =16),axis.text =element_text(size =12),panel.grid.major.x =element_blank() )
Detailed Health Status Comparison
Show Code
# Stacked bar chart showing full breakdownstatus_comparison <- trees_with_borough %>%st_drop_geometry() %>%filter(CounDist %in% comparison_districts) %>%count(CounDist, status) %>%group_by(CounDist) %>%mutate(percentage = n /sum(n) *100)ggplot(status_comparison, aes(x =factor(CounDist), y = percentage, fill = status)) +geom_col(position ="stack") +scale_fill_manual(values =c("Alive"="#2e7d32", "Dead"="#c62828","Stump"="#6d4c41","Poor"="#f57c00"),name ="Tree Status" ) +labs(title ="Tree Health Status Distribution Across Queens Districts",subtitle ="District 19 shows a concerning proportion of dead, poor, and stump conditions",x ="Council District",y ="Percentage of Trees (%)",caption ="Stacked bars show relative distribution of all tree statuses" ) +theme_minimal() +theme(plot.title =element_text(face ="bold", size =14),legend.position ="right" )
Conclusion and Call to Action
The data speaks clearly: Council District 19 requires immediate attention to address its urban forestry crisis. With 1438 trees requiring intervention, the Queens Green Revival Initiative represents a critical investment in public health, environmental quality, and community well-being.
Additionally, analysis of citywide risk assessment data reveals 1265399 documented tree hazards requiring attention, while 1378889 pending work orders demonstrate the scale of maintenance backlogs across NYC. This context underscores the urgency of proactive interventions like our proposed program.
This program will: - Improve air quality by replacing non-functional trees with healthy, carbon-sequestering specimens - Reduce urban heat island effects through expanded canopy coverage - Enhance property values and neighborhood aesthetics - Demonstrate environmental justice by ensuring all Queens residents have access to a healthy urban forest - Build climate resilience by selecting species adapted to future climate conditions
I respectfully request NYC Parks Department funding of $525,000 to implement this vital initiative over the next 18 months, positioning District 19 as a model for urban forest restoration citywide.